// File:    parser.h
// Author:  Brian Vanderburg II
// Purpose: Parser object to help parse expression
//------------------------------------------------------------------------------


#ifndef __EXPREVAL_PARSER_H
#define __EXPREVAL_PARSER_H

// Includes
#include <vector>
#include <string>
//#include <iostream>

// Part of expreval namespace
namespace ExprEval
{
// Forward declarations
class Expression;
class Node;

// Token class
//--------------------------------------------------------------------------
class Token
{
public:

    // Token type
    enum TokenType
    {
        TypeUnknown = 0,

        // Basic types
        TypeOpenParenthesis,  // '('
        TypeCloseParenthesis, // ')'
        TypeEqual,            // '='
        TypePlus,             // '+'
        TypeHyphen,           // '-'
        TypeAsterisk,         // '*'
        TypeForwardSlash,     // '/'
        TypeGT,               // '>'
        TypeGE,               // '>='
        TypeLT,               // '<'
        TypeLE,               // '<='
        TypeEQ,               // '=='
        TypeNE,               // '!='
        TypeAnd,              // '&&'
        TypeOr,               // '||'
        TypeNot,              // '!'
        TypeHat,              // '^'
        TypeAmpersand,        // '&'
        TypeComma,            // ','
        TypeSemicolon,        // ';'
        TypeIdentifier,       // name
        TypeValue             // 0.2, .6, 2.1
    };

    // Constructors
    Token (TokenType type, std::string::size_type start, std::string::size_type end);
    Token (const std::string &ident, std::string::size_type start, std::string::size_type end); // May throw if can not copy string
    Token (double value, std::string::size_type start, std::string::size_type end);

    // Information
    TokenType GetType() const;
    const std::string &GetIdentifier() const;
    double GetValue() const;

    std::string::size_type GetStart() const;
    std::string::size_type GetEnd() const;
    friend std::ostream& operator << (std::ostream& os, const Token& rhs);

private:
    TokenType m_type; // Type of token
    std::string m_ident; // If type is Identifier
    double m_value; // If type is Value

    std::string::size_type m_start, m_end;
};



// Parser class
//--------------------------------------------------------------------------
class Parser
{
public:
    typedef ::std::vector<Token*>::size_type size_type;

    Parser(Expression *expr);
    ~Parser();

    //Node *Parse (const std::string &exstr);
    /**
     * parse the exstr and if the derivative to var_symbol is required,
     * save the derivative information
     */
    Node *Parse (const std::string &exstr, bool& good_parse);

    Node *ParseRegion (size_type start, size_type end, bool &good_parse);

    const Token &operator[] (size_type pos) const;

private:

    void BuildTokens (const std::string &exstr, bool& good_parse);

    Expression *m_expr;
    std::vector<Token> m_tokens; // Store token and not pointer to token

private:

    Parser(const Parser&);
    Parser& operator = (const Parser&);
};

}

#endif // __EXPREVAL_PARSER_H
